package com.ganlucode.sipmock.sip.mock;

import com.ganlucode.sipmock.sip.mock.entity.KeepAliveParam;
import com.ganlucode.sipmock.sip.mock.entity.MockParam;
import com.ganlucode.sipmock.sip.request.SipRequestFactory;
import com.ganlucode.sipmock.utils.SipHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.sip.ClientTransaction;
import javax.sip.SipException;
import javax.sip.TransactionUnavailableException;
import javax.sip.message.Request;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author GanLu
 * @date 2020-05-26 16:38
 */
@Slf4j
@EnableScheduling
@Service("keepAliveMock")
public class KeepAliveMock implements ISipMock<KeepAliveParam> {

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    /**
     * 在ScheduledFuture中有一个cancel可以停止定时任务。
     */
    private  ScheduledFuture<?> future;

    private ReentrantLock lock = new ReentrantLock();

    @Autowired
    private SipHelper sipHelper;

    @Autowired
    private SipRequestFactory sipRequestFactory;

    @PostConstruct
    private void init(){
        threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.initialize();
    }

    @Override
    public void start(MockParam<KeepAliveParam> param) throws Exception {
        try {
            lock.lock();
            if (future!=null && !future.isCancelled()){
                future.cancel(true);
            }
            future = threadPoolTaskScheduler.schedule(this::sendKeepAlived,
                    new CronTrigger("0/30 * * * * ? "));
            log.info("KeepAliveMock----start");
        } finally{
            lock.unlock();
        }

    }

    @Override
    public void stop(MockParam<KeepAliveParam> param) throws Exception {
        if (future != null) {
            future.cancel(true);
        }
        log.info("KeepAliveMock----stop");
    }

    private void sendKeepAlived(){
        try {
            Request request = sipRequestFactory.createKeepaliveRequest();
            ClientTransaction clientTransaction = sipHelper.getSipProvider().getNewClientTransaction(request);
            log.info("发送KeepAlive");
            clientTransaction.sendRequest();
        } catch (TransactionUnavailableException e) {
            e.printStackTrace();
        } catch (SipException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
